//------------------------------------------------------------
//  Filename: vga_dma_ip_v1_0_S00_AXI.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2016-08-04 11:03
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module vga_dma_ip_v1_0_S00_AXI #(
    parameter integer C_S_AXI_DATA_WIDTH    = 32,
    parameter integer C_S_AXI_ADDR_WIDTH    = 4
) (
    input  wire                                 S_AXI_ACLK,
    input  wire                                 S_AXI_ARESETN,
    input  wire [C_S_AXI_ADDR_WIDTH-1 : 0     ] S_AXI_AWADDR,
    input  wire [2 : 0                        ] S_AXI_AWPROT,
    input  wire                                 S_AXI_AWVALID,
    output wire                                 S_AXI_AWREADY,
    input  wire [C_S_AXI_DATA_WIDTH-1 : 0     ] S_AXI_WDATA,
    input  wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0 ] S_AXI_WSTRB,
    input  wire                                 S_AXI_WVALID,
    output wire                                 S_AXI_WREADY,
    //-------------------------------------------------------- 
    output wire [1 : 0                        ] S_AXI_BRESP,
    output wire                                 S_AXI_BVALID,
    input  wire                                 S_AXI_BREADY,
    //-------------------------------------------------------- 
    input  wire [C_S_AXI_ADDR_WIDTH-1 : 0     ] S_AXI_ARADDR,
    input  wire [2 : 0                        ] S_AXI_ARPROT,
    input  wire                                 S_AXI_ARVALID,
    output wire                                 S_AXI_ARREADY,
    output wire [C_S_AXI_DATA_WIDTH-1 : 0     ] S_AXI_RDATA,
    output wire [1 : 0                        ] S_AXI_RRESP,
    output wire                                 S_AXI_RVALID,
    input  wire                                 S_AXI_RREADY,
    //--------------------------------------------------------
    output wire [31:0                         ] start_addr,
    output wire [31:0                         ] line_cnt,
    output wire [31:0                         ] row_cnt, 
    output wire                                 vga_pwr_en,
    input  wire                                 data_err,
    output reg                                  mm_read_start,
    input  wire                                 mm_read_done    
);
//--------------------------------------------------------
reg [C_S_AXI_ADDR_WIDTH-1 : 0 ] axi_awaddr;
reg                             axi_awready;
reg                             axi_wready;
reg [1 : 0                    ] axi_bresp;
reg                             axi_bvalid;
reg [C_S_AXI_ADDR_WIDTH-1 : 0 ] axi_araddr;
reg                             axi_arready;
reg [C_S_AXI_DATA_WIDTH-1 : 0 ] axi_rdata;
reg [1 : 0                    ] axi_rresp;
reg                             axi_rvalid;
//--------------------------------------------------------
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer OPT_MEM_ADDR_BITS = 1;
//--------------------------------------------------------
reg [C_S_AXI_DATA_WIDTH-1:0]    slv_reg0;
reg [C_S_AXI_DATA_WIDTH-1:0]    slv_reg1;
reg [C_S_AXI_DATA_WIDTH-1:0]    slv_reg2;
reg [C_S_AXI_DATA_WIDTH-1:0]    slv_reg3;
reg [C_S_AXI_DATA_WIDTH-1:0]    reg_data_out;
wire     slv_reg_rden;
wire     slv_reg_wren;
integer  byte_index;
//--------------------------------------------------------
assign S_AXI_AWREADY   = axi_awready;
assign S_AXI_WREADY    = axi_wready;
assign S_AXI_BRESP     = axi_bresp;
assign S_AXI_BVALID    = axi_bvalid;
assign S_AXI_ARREADY   = axi_arready;
assign S_AXI_RDATA     = axi_rdata;
assign S_AXI_RRESP     = axi_rresp;
assign S_AXI_RVALID    = axi_rvalid;
//--------------------------------------------------------
always @( posedge S_AXI_ACLK )   begin
    if ( S_AXI_ARESETN == 1'b0 )  begin
        axi_awready <= 1'b0;
    end 
    else begin    
        if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) begin
            axi_awready <= 1'b1;
        end
        else begin
            axi_awready <= 1'b0;
        end
    end 
end       
//--------------------------------------------------------
always @( posedge S_AXI_ACLK )begin
    if ( S_AXI_ARESETN == 1'b0 )begin
        axi_awaddr <= 0;
    end 
    else if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID) begin
        axi_awaddr <= S_AXI_AWADDR;
    end 
end       
//--------------------------------------------------------
always @( posedge S_AXI_ACLK ) begin 
    if ( S_AXI_ARESETN == 1'b0 ) begin 
        axi_wready <= 1'b0;
    end
    else begin 
        if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID) begin 
            axi_wready <= 1'b1;
        end
        else begin 
            axi_wready <= 1'b0;
        end
    end 
end
//--------------------------------------------------------
always @( posedge S_AXI_ACLK ) begin
    if ( S_AXI_ARESETN == 1'b0 ) begin
        slv_reg0 <= 0;
        slv_reg1 <= 640;
        slv_reg2 <= 480;
        slv_reg3 <= 0;
    end
    else begin
        if (slv_reg_wren) begin
            case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
            2'h0:  begin
                slv_reg0 <= S_AXI_WDATA;
            end
            2'h1:  begin
                slv_reg1 <= S_AXI_WDATA;
            end
            2'h2:  begin
                slv_reg2 <= S_AXI_WDATA;
            end
            2'h3:  begin
                slv_reg3 <= S_AXI_WDATA;
            end
            default : begin
                slv_reg0 <= slv_reg0;
                slv_reg1 <= slv_reg1;
                slv_reg2 <= slv_reg2;
                slv_reg3 <= slv_reg3;
            end
            endcase
        end
    end
end
//--------------------------------------------------------
always @( posedge S_AXI_ACLK ) begin
    if ( S_AXI_ARESETN == 1'b0 ) begin
        axi_bvalid <= 0;
        axi_bresp <= 2'b0;
    end
    else begin
        if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) begin
            axi_bvalid <= 1'b1;
            axi_bresp <= 2'b0; // 'OKAY' response
        end // work error responses in future
        else begin
            if (S_AXI_BREADY && axi_bvalid) begin
                axi_bvalid <= 1'b0;
            end
        end
    end
end
//--------------------------------------------------------
always @( posedge S_AXI_ACLK ) begin
    if ( S_AXI_ARESETN == 1'b0 ) begin
        axi_arready <= 1'b0;
        axi_araddr <= 32'b0;
    end
    else begin
        if (~axi_arready && S_AXI_ARVALID) begin
            axi_arready <= 1'b1;
            axi_araddr <= S_AXI_ARADDR;
        end
        else begin
            axi_arready <= 1'b0;
        end
    end
end
//--------------------------------------------------------
always @( posedge S_AXI_ACLK ) begin
    if ( S_AXI_ARESETN == 1'b0 ) begin
        axi_rvalid <= 0;
        axi_rresp <= 0;
    end
    else begin
        if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) begin
            axi_rvalid <= 1'b1;
            axi_rresp <= 2'b0; // 'OKAY' response
        end
        else if (axi_rvalid && S_AXI_RREADY) begin
            axi_rvalid <= 1'b0;
        end
    end
end
//--------------------------------------------------------
always @(*) begin
    case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
        2'h0 : reg_data_out = slv_reg0;
        2'h1 : reg_data_out = slv_reg1;
        2'h2 : reg_data_out = slv_reg2;
        2'h3 : reg_data_out = slv_reg3;
        default : reg_data_out = 0;
    endcase
end
//--------------------------------------------------------
always @( posedge S_AXI_ACLK ) begin
    if ( S_AXI_ARESETN == 1'b0 ) begin
        axi_rdata <= 0;
    end
    else begin
        if (slv_reg_rden) begin
            axi_rdata <= reg_data_out; // register read data
        end
    end
end
//--------------------------------------------------------
assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
//--------------------------------------------------------
 
//assign  start_addr     = slv_reg0;
//assign  line_cnt       = slv_reg1;
//assign  row_cnt        = slv_reg2; 
assign  mm_read_start  = 1;

assign  start_addr     = 0;
assign  line_cnt       = 64;
assign  row_cnt        = 48; 
//assign  mm_read_start  = 0;

endmodule

